import * as PIXI from "pixi.js";
import { ResourceManager } from "./ResourceManager";
import { IRenderer } from "../types/IRenderer";

/**
 * 角色渲染器实现
 *
 * 负责管理PixiJS角色精灵的渲染、变换和外观更新
 * 提供角色身体、衣服、帽子等部件的加载和管理功能
 * 支持位置、缩放、旋转等变换操作
 */
export class CharacterRenderer implements IRenderer {
  /** PixiJS应用实例 */
  private app: PIXI.Application;

  /** 角色容器，包含所有角色部件 */
  private character: PIXI.Container;

  /** 身体精灵 */
  private body: PIXI.Sprite | null = null;

  /** 衣服精灵 */
  private clothes: PIXI.Sprite | null = null;

  /** 帽子精灵 */
  private hat: PIXI.Sprite | null = null;

  /** 左手精灵 */
  private leftHand: PIXI.Sprite | null = null;

  /** 右手精灵 */
  private rightHand: PIXI.Sprite | null = null;

  /** 资源管理器，用于加载纹理 */
  private resourceManager: ResourceManager;

  /** 角色初始状态，用于重置功能 */
  private initialState: {
    position: { x: number; y: number };
    scale: { x: number; y: number };
    rotation: number;
  };

  /**
   * 构造函数
   *
   * @param container HTML容器元素
   * @param config 渲染配置
   * @param resourceManager 资源管理器实例
   *
   * 功能：
   * 1. 创建PixiJS应用实例
   * 2. 设置画布尺寸和背景色
   * 3. 创建角色容器并居中放置
   * 4. 保存初始状态用于重置
   */
  constructor(
    container: HTMLElement,
    config: { width: number; height: number; backgroundColor: number },
    resourceManager: ResourceManager
  ) {
    this.resourceManager = resourceManager;

    // 创建PixiJS应用
    this.app = new PIXI.Application({
      width: config.width,
      height: config.height,
      backgroundColor: config.backgroundColor,
      antialias: true, // 抗锯齿
      resolution: window.devicePixelRatio || 1, // 设备像素比
      autoDensity: true, // 自动密度
    });

    // 将画布添加到容器（兼容PixiJS v7和v8）
    const canvas = (this.app as any).canvas || this.app.view;
    container.appendChild(canvas as HTMLCanvasElement);

    // 创建角色容器
    this.character = new PIXI.Container();
    this.character.x = config.width / 2; // 水平居中
    this.character.y = config.height / 2; // 垂直居中
    this.app.stage.addChild(this.character);

    // 保存初始状态
    this.initialState = {
      position: { x: this.character.x, y: this.character.y },
      scale: { x: this.character.scale.x, y: this.character.scale.y },
      rotation: this.character.rotation,
    };
  }

  /**
   * 加载身体部件
   *
   * @param path 身体纹理路径
   * @param onError 错误回调函数
   *
   * 功能：
   * 1. 通过资源管理器加载纹理
   * 2. 移除旧的身体精灵（如果存在）
   * 3. 创建新的身体精灵并添加到角色容器
   * 4. 设置精灵锚点为中心点
   */
  async loadBody(path: string, onError?: (error: string) => void) {
    try {
      const texture = await this.resourceManager.loadTexture(path);

      // 移除旧的身体精灵
      if (this.body) {
        this.character.removeChild(this.body);
      }

      // 创建新的身体精灵
      this.body = new PIXI.Sprite(texture);
      this.body.anchor.set(0.5); // 设置锚点为中心
      this.character.addChildAt(this.body, 0); // 添加到最底层
    } catch (error) {
      onError?.(`加载身体失败: ${error}`);
    }
  }

  /**
   * 加载衣服部件
   *
   * @param path 衣服纹理路径，为空时移除衣服
   * @param onError 错误回调函数
   *
   * 功能：
   * 1. 如果路径为空，移除现有衣服
   * 2. 否则加载新的衣服纹理
   * 3. 移除旧的衣服精灵（如果存在）
   * 4. 创建新的衣服精灵并添加到角色容器
   */
  async loadClothes(path: string, onError?: (error: string) => void) {
    if (!path) {
      // 移除衣服
      if (this.clothes) {
        this.character.removeChild(this.clothes);
        this.clothes = null;
      }
      return;
    }

    try {
      const texture = await this.resourceManager.loadTexture(path);

      // 移除旧的衣服精灵
      if (this.clothes) {
        this.character.removeChild(this.clothes);
      }

      // 创建新的衣服精灵
      this.clothes = new PIXI.Sprite(texture);
      this.clothes.anchor.set(0.5);
      this.character.addChild(this.clothes);
    } catch (error) {
      onError?.(`加载衣服失败: ${error}`);
    }
  }

  /**
   * 加载帽子部件
   *
   * @param path 帽子纹理路径，为空时移除帽子
   * @param onError 错误回调函数
   *
   * 功能：
   * 1. 如果路径为空，移除现有帽子
   * 2. 否则加载新的帽子纹理
   * 3. 移除旧的帽子精灵（如果存在）
   * 4. 创建新的帽子精灵并添加到角色容器
   */
  async loadHat(path: string, onError?: (error: string) => void) {
    if (!path) {
      // 移除帽子
      if (this.hat) {
        this.character.removeChild(this.hat);
        this.hat = null;
      }
      return;
    }

    try {
      const texture = await this.resourceManager.loadTexture(path);

      // 移除旧的帽子精灵
      if (this.hat) {
        this.character.removeChild(this.hat);
      }

      // 创建新的帽子精灵
      this.hat = new PIXI.Sprite(texture);
      this.hat.anchor.set(0.5);
      this.character.addChild(this.hat);
    } catch (error) {
      onError?.(`加载帽子失败: ${error}`);
    }
  }

  /**
   * 加载左手部件
   *
   * @param path 左手纹理路径
   * @param position 左手位置坐标
   * @param onError 错误回调函数
   */
  async loadLeftHand(
    path: string,
    position?: { x: number; y: number },
    onError?: (error: string) => void
  ) {
    if (!path) {
      // 移除左手
      if (this.leftHand) {
        this.character.removeChild(this.leftHand);
        this.leftHand = null;
      }
      return;
    }

    try {
      const texture = await this.resourceManager.loadTexture(path);

      // 移除旧的左手精灵
      if (this.leftHand) {
        this.character.removeChild(this.leftHand);
      }

      // 创建新的左手精灵
      this.leftHand = new PIXI.Sprite(texture);
      this.leftHand.name = "leftHand"; // 设置名称用于动画识别
      this.leftHand.anchor.set(0.5);

      // 使用传入的位置或默认位置
      const leftPos = position || this.getHandDefaultPosition("left");
      this.leftHand.x = leftPos.x;
      this.leftHand.y = leftPos.y;

      // 根据身体颜色调整手部颜色
      this.adjustHandColor(this.leftHand);

      this.character.addChild(this.leftHand);
    } catch (error) {
      onError?.(`加载左手失败: ${error}`);
    }
  }

  /**
   * 加载右手部件
   *
   * @param path 右手纹理路径
   * @param position 右手位置坐标
   * @param onError 错误回调函数
   */
  async loadRightHand(
    path: string,
    position?: { x: number; y: number },
    onError?: (error: string) => void
  ) {
    if (!path) {
      // 移除右手
      if (this.rightHand) {
        this.character.removeChild(this.rightHand);
        this.rightHand = null;
      }
      return;
    }

    try {
      const texture = await this.resourceManager.loadTexture(path);

      // 移除旧的右手精灵
      if (this.rightHand) {
        this.character.removeChild(this.rightHand);
      }

      // 创建新的右手精灵
      this.rightHand = new PIXI.Sprite(texture);
      this.rightHand.name = "rightHand"; // 设置名称用于动画识别
      this.rightHand.anchor.set(0.5);

      // 使用传入的位置或默认位置
      const rightPos = position || this.getHandDefaultPosition("right");
      this.rightHand.x = rightPos.x;
      this.rightHand.y = rightPos.y;

      // 根据身体颜色调整手部颜色
      this.adjustHandColor(this.rightHand);

      this.character.addChild(this.rightHand);
    } catch (error) {
      onError?.(`加载右手失败: ${error}`);
    }
  }

  /**
   * 设置角色位置
   *
   * @param x X坐标
   * @param y Y坐标
   */
  setPosition(x: number, y: number): void {
    this.character.x = x;
    this.character.y = y;
  }

  /**
   * 设置角色缩放
   *
   * @param x X轴缩放比例
   * @param y Y轴缩放比例
   */
  setScale(x: number, y: number): void {
    this.character.scale.set(x, y);
  }

  /**
   * 设置角色旋转
   *
   * @param angle 旋转角度（弧度）
   */
  setRotation(angle: number): void {
    this.character.rotation = angle;
  }

  /**
   * 获取角色位置
   *
   * @returns { x: number; y: number } 当前位置坐标
   */
  getPosition(): { x: number; y: number } {
    return { x: this.character.x, y: this.character.y };
  }

  /**
   * 获取角色缩放
   *
   * @returns { x: number; y: number } 当前缩放比例
   */
  getScale(): { x: number; y: number } {
    return { x: this.character.scale.x, y: this.character.scale.y };
  }

  /**
   * 获取角色旋转
   *
   * @returns number 当前旋转角度（弧度）
   */
  getRotation(): number {
    return this.character.rotation;
  }

  /**
   * 重置角色到初始状态
   *
   * 功能：
   * 将角色的位置、缩放、旋转恢复到创建时的初始值
   */
  reset(): void {
    this.character.x = this.initialState.position.x;
    this.character.y = this.initialState.position.y;
    this.character.scale.set(
      this.initialState.scale.x,
      this.initialState.scale.y
    );
    this.character.rotation = this.initialState.rotation;
  }

  /**
   * 获取角色容器
   *
   * @returns PIXI.Container 角色容器对象
   */
  getCharacter(): PIXI.Container {
    return this.character;
  }

  /**
   * 获取PixiJS应用实例
   *
   * @returns PIXI.Application PixiJS应用对象
   */
  getApp(): PIXI.Application {
    return this.app;
  }

  /**
   * 调整手部颜色以匹配身体
   *
   * @param handSprite 手部精灵
   */
  private adjustHandColor(handSprite: PIXI.Sprite): void {
    if (!this.body) return;

    // 获取身体的主要颜色（这里简化处理，实际可能需要更复杂的颜色提取）
    // 根据身体文件名判断颜色
    // const bodyTexture = this.body.texture;
    // const bodyBaseTexture = bodyTexture.baseTexture; // 暂时未使用

    // 这里可以根据需要实现更复杂的颜色匹配逻辑
    // 暂时使用默认颜色
    handSprite.tint = 0xffffff; // 保持原色
  }

  /**
   * 获取手部默认定位坐标
   *
   * @param handType 手部类型 ('left' | 'right')
   * @returns 手部应该放置的坐标
   */
  private getHandDefaultPosition(handType: "left" | "right"): {
    x: number;
    y: number;
  } {
    // 默认定位（基于手部SVG的viewBox和手臂位置）
    // 手部SVG viewBox: 0 0 100 150，手臂位置在SVG内部
    const positions = {
      left: { x: 0, y: 0 }, // 左肩位置，让手臂从肩膀开始
      right: { x: 0, y: 0 }, // 右肩位置，让手臂从肩膀开始
    };

    return positions[handType];
  }

  /**
   * 设置手部位置
   *
   * @param handType 手部类型 ('left' | 'right')
   * @param x X坐标
   * @param y Y坐标
   */
  setHandPosition(handType: "left" | "right", x: number, y: number): void {
    const hand = handType === "left" ? this.leftHand : this.rightHand;
    if (hand) {
      hand.x = x;
      hand.y = y;
    }
  }

  /**
   * 获取手部位置
   *
   * @param handType 手部类型 ('left' | 'right')
   * @returns 手部当前位置坐标
   */
  getHandPosition(handType: "left" | "right"): { x: number; y: number } | null {
    const hand = handType === "left" ? this.leftHand : this.rightHand;
    if (hand) {
      return { x: hand.x, y: hand.y };
    }
    return null;
  }

  /**
   * 销毁渲染器
   *
   * 功能：
   * 销毁PixiJS应用实例，释放内存和GPU资源
   */
  destroy(): void {
    this.app.destroy(true);
  }
}
